home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / perl / msds-prl / prl386l1.zoo / popen.c < prev    next >
C/C++ Source or Header  |  1992-07-29  |  4KB  |  190 lines

  1. static char *rcsid = "$Id: POPEN.C 1.1 92/07/19 14:25:55 doi Exp $";
  2. /* RCSfile: popen.c,v Revision: 4.0.1.1 Date: 91/06/07 11:22:52 
  3.  *
  4.  *    (C) Copyright 1988, 1990 Diomidis Spinellis.
  5.  *
  6.  *    You may distribute under the terms of either the GNU General Public
  7.  *    License or the Artistic License, as specified in the README file.
  8.  *
  9.  * Log:    popen.c,v 
  10.  * Revision 4.0.1.1  91/06/07  11:22:52  lwall
  11.  * patch4: new copyright notice
  12.  * 
  13.  * Revision 4.0  91/03/20  01:34:50  lwall
  14.  * 4.0 baseline.
  15.  * 
  16.  * Revision 3.0.1.2  90/08/09  04:04:42  lwall
  17.  * patch19: various MSDOS and OS/2 patches folded in
  18.  * 
  19.  * Revision 3.0.1.1  90/03/27  16:11:57  lwall
  20.  * patch16: MSDOS support
  21.  * 
  22.  * Revision 1.1  90/03/18  20:32:20  dds
  23.  * Initial revision
  24.  *
  25.  */
  26.  
  27. /*
  28.  * Popen and pclose for MS-DOS
  29.  */
  30.  
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #ifndef DJGPP
  34. #include <process.h>    /* doesn't exist in DJGPP */
  35. #endif /* !DJGPP */
  36.  
  37. /*
  38.  * Possible actions on an popened file
  39.  */
  40. enum action {
  41.     delete,             /* Used for "r". Delete the tmp file */
  42.     execute                /* Used for "w". Execute the command. */
  43. };
  44.  
  45. /*
  46.  * Linked list of things to do at the end of the program execution.
  47.  */
  48. static struct todo {
  49.     FILE *f;            /* File we are working on (to fclose) */
  50.     const char *name;        /* Name of the file (to unlink) */
  51.     const char *command;        /* Command to execute */
  52.     enum action what;        /* What to do (execute or delete) */
  53.     struct todo *next;        /* Next structure */
  54. } *todolist;
  55.  
  56.  
  57. /* Clean up function */
  58. static int close_pipes(void);
  59.  
  60. /*
  61.  * Add a file f running the command command on file name to the list
  62.  * of actions to be done at the end.  The action is specified in what.
  63.  * Return -1 on failure, 0 if ok.
  64.  */
  65. static int
  66. add(FILE *f, const char *command, const char *name, enum action what)
  67. {
  68.     struct todo    *p;
  69.  
  70.     if ((p = (struct todo *) malloc(sizeof(struct todo))) == NULL)
  71.         return -1;
  72.     p->f = f;
  73.     p->command = command;
  74.     p->name = name;
  75.     p->what = what;
  76.     p->next = todolist;
  77.     todolist = p;
  78.     return 0;
  79. }
  80.  
  81. FILE *
  82. mypopen(const char *command, const char *t)
  83. {
  84.     char buff[256];
  85.     char *name;
  86.     FILE *f;
  87.     static init = 0;
  88.  
  89.     if (!init)
  90. #ifndef DJGPP
  91.         if (onexit(close_pipes) == NULL)
  92.             return NULL;
  93.         else
  94. #endif /* !DJGPP */
  95.             init++;
  96.  
  97.     if ((name = tempnam((char*)NULL, "pp")) == NULL)
  98.         return NULL;
  99.  
  100.     switch (*t) {
  101.     case 'r':
  102.         sprintf(buff, "%s >%s", command, name);
  103.         if (system(buff) || (f = fopen(name, "r")) == NULL) {
  104.             free(name);
  105.             return NULL;
  106.         }
  107.         if (add(f, command, name, delete)) {
  108.             (void)fclose(f);
  109.             (void)unlink(name);
  110.             free(name);
  111.             return NULL;
  112.         }
  113.         return f;
  114.     case 'w':
  115.         if ((f = fopen(name, "w")) == NULL) {
  116.             free(name);
  117.             return NULL;
  118.         }
  119.         if (add(f, command, name, execute)) {
  120.             (void)fclose(f);
  121.             (void)unlink(name);
  122.             free(name);
  123.             return NULL;
  124.         }
  125.         return f;
  126.     default:
  127.         free(name);
  128.         return NULL;
  129.     }
  130. }
  131.  
  132. int
  133. mypclose(FILE *f)
  134. {
  135.     struct todo *p, **prev;
  136.     char buff[256];
  137.     const char *name;
  138.     int status;
  139.  
  140.     for (p = todolist, prev = &todolist; p; prev = &(p->next), p = p->next)
  141.         if (p->f == f) {
  142.             *prev = p->next;
  143.             name = p->name;
  144.             switch (p->what) {
  145.             case delete:
  146.                 free(p);
  147.                 if (fclose(f) == EOF) {
  148.                     (void)unlink(name);
  149.                     status = EOF;
  150.                 } else if (unlink(name) < 0)
  151.                     status = EOF;
  152.                 else
  153.                     status = 0;
  154.                 free((void*)name);
  155.                 return status;
  156.             case execute:
  157.                 (void)sprintf(buff, "%s <%s", p->command, p->name);
  158.                 free(p);
  159.                 if (fclose(f) == EOF) {
  160.                     (void)unlink(name);
  161.                     status = EOF;
  162.                 } else if (system(buff)) {
  163.                     (void)unlink(name);
  164.                     status = EOF;
  165.                 } else if (unlink(name) < 0)
  166.                     status = EOF;
  167.                 else
  168.                     status = 0;
  169.                 free((void*)name);
  170.                 return status;
  171.             default:
  172.                 return EOF;
  173.             }
  174.         }
  175.     return EOF;
  176. }
  177.  
  178. /*
  179.  * Clean up at the end.  Called by the onexit handler.
  180.  */
  181. static int
  182. close_pipes(void)
  183. {
  184.     struct todo    *p;
  185.  
  186.     for (p = todolist; p; p = p->next)
  187.         (void)mypclose(p->f);
  188.     return 0;
  189. }
  190.